import CodePush, { DownloadProgress, SyncStatusChangedCallback } from 'react-native-code-push';

type CheckCallback = (update: boolean) => void;
export type ProgressCallback = (percent: number, DownloadProgress) => void;

export const StatusStr = {
  [CodePush.SyncStatus.UP_TO_DATE]: '最新版本',
  [CodePush.SyncStatus.UPDATE_INSTALLED]: '下次打开更新',
  [CodePush.SyncStatus.UPDATE_IGNORED]: '忽略更新',
  [CodePush.SyncStatus.UNKNOWN_ERROR]: '检查失败',
  [CodePush.SyncStatus.SYNC_IN_PROGRESS]: '更新中...',
  [CodePush.SyncStatus.CHECKING_FOR_UPDATE]: '检查更新...',
  [CodePush.SyncStatus.AWAITING_USER_ACTION]: '等待中...',
  [CodePush.SyncStatus.DOWNLOADING_PACKAGE]: '下载更新...',
  [CodePush.SyncStatus.INSTALLING_UPDATE]: '安装更新...',
};
/**
 * 需要重新检查热更新的状态
 * @type {any[]}
 */
export const ShouldReCheckStatus = [
  CodePush.SyncStatus.UNKNOWN_ERROR,
  CodePush.SyncStatus.UPDATE_IGNORED,
  CodePush.SyncStatus.UP_TO_DATE,
];
export default class CodePushManager {
  static status: CodePush.SyncStatus;
  static progressListeners: Map<string, ProgressCallback> = new Map();
  static statusListeners: Map<string, SyncStatusChangedCallback> = new Map();
  static addListener(
    key: string,
    downloadListener: ProgressCallback,
    statusListener: SyncStatusChangedCallback) {
    if (!key) return;
    downloadListener&&CodePushManager.progressListeners.set(key, downloadListener);
    statusListener&&CodePushManager.statusListeners.set(key, statusListener);
  }
  static removeListener(key: string) {
    if (!key) return;
    CodePushManager.progressListeners.delete(key);
    CodePushManager.statusListeners.delete(key);
  }
  static checkVersion(callback: CheckCallback) {
    CodePush.checkForUpdate().then(update => {
      callback(!!update);
    });
  }

  /**
   * 静默更新
   * @param installMode 安装更新时机
   */
  static syncSilently(installMode=CodePush.InstallMode.ON_NEXT_RESUME) {
    // if (__DEV__) return;
    CodePush.sync({
      installMode,
    }, (status: CodePush.SyncStatus) => {
      CodePushManager.status = status;
      CodePushManager.statusListeners.forEach((listener: SyncStatusChangedCallback) => {
        listener&&listener(status);
      });
    }, (progress: DownloadProgress) => {
      const { totalBytes, receivedBytes } = progress;
      let percent = receivedBytes/totalBytes;
      percent = parseFloat(percent||0).toFixed(2);
      CodePushManager.progressListeners.forEach((listener: ProgressCallback) => {
        listener&&listener(percent, progress);
      });
    });
  }
  /**
   * 默认窗口热更新
   * @param installMode安装模式
   *    ON_NEXT_RESUME 下次恢复到前台时
   *    ON_NEXT_RESTART 下一次重启时
   *    IMMEDIATE 马上更新
   * @param updateDialog 对话框
   */
  static syncEasyDialog({
                          installMode, updateDialog,
                        } = {
    installMode: CodePush.InstallMode.IMMEDIATE,
    updateDialog: {
      // 是否显示更新描述
      appendReleaseDescription: true,
      // 更新描述的前缀。 默认为"Description"
      descriptionPrefix: '更新内容：',
      // 强制更新按钮文字，默认为continue
      mandatoryContinueButtonLabel: '立即更新',
      // 强制更新时的信息. 默认为"An update is available that must be installed."
      mandatoryUpdateMessage: '必须更新后才能使用',
      // 非强制更新时，按钮文字,默认为"ignore"
      optionalIgnoreButtonLabel: '稍后',
      // 非强制更新时，确认按钮文字. 默认为"Install"
      optionalInstallButtonLabel: '后台更新',
      // 非强制更新时，检查到更新的消息文本
      optionalUpdateMessage: '有新版本了，是否更新？',
      // Alert窗口的标题
      title: '更新提示'
    },
  }) {
    CodePush.sync({
      installMode,
      updateDialog,
    });
  }
}
